<?php

trait ModelTrait
{
	/*-20181030 New Model Query----------------------------*/

    //表名称(无前缀)
    protected $tableName; 
    
    //表主键(默认id)
    protected $primary_key = "`id`"; 

    /*
    * 20180927
    * 新增模型要执行查询表
    * 按主键查询
    */
    public function table($table)
    {
        $this->tableName = $table;
        return $this;
    }
    /*
    * 20180927
    * 新增模型查询方法
    * 按主键查询
    */
    public function findByPk($id=0,$primary_key='id',$table=false)
    {
        $table = $table?$table:$this->tableName;
        $primary_key = $primary_key?$primary_key:$this->primary_key;
        $sql = "SELECT * FROM ". $this->_prefix['primary'] . $table ." WHERE `".$primary_key."`=".intval($id);
        return $this->db->getrow($sql);
    }
    
    /*
    * 20180927
    * 新增模型查询方法
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回二维数组
    */
    public function findAllByAttributes($where, $select="*", $table=false)
    {
        if (is_array($select)) $select = implode(',', $select);

        $whereSql = $this->formatWhereSql($where);

        $table = $table?$table:$this->tableName;

        $sql = 'SELECT '. $select .' FROM '. $this->_prefix['primary'] . $table .' where '. $whereSql;

        return $this->db->sql($sql);
    }

    /*
    * 20180927
    * 新增模型查询方法获取某一列数据
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回一维数组
    */
    public function findColumnByAttributes($where, $column, $table=false)
    {
        
        $whereSql = $this->formatWhereSql($where);

        $table = $table?$table:$this->tableName;

        $sql = 'SELECT '. $column .' FROM '. $this->_prefix['primary'] . $table .' where '. $whereSql;

        $rows = $this->db->sql($sql);

        if (count($rows)>0) {
            foreach ($rows as $key => $value) {
                $rows[$key] = $value[$column];
            }
        }

        return $rows;
    }


    /*
    * 20180927
    * 新增模型查询方法
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回一维数组
    */
    public function findByAttributes($where, $select="*", $table=false)
    {
        if (is_array($select)) $select = implode(',', $select);

        $whereSql = $this->formatWhereSql($where);

        $table = $table?$table:$this->tableName;
        
        $sql = 'SELECT '. $select .' FROM '. $this->_prefix['primary'] . $table .' where '. $whereSql .' limit 1';
        
        return $this->db->getrow($sql);
    }

    /*
    * 20180927
    * 新增模型查询方法 统计
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回int
    */
    public function countByAttributes($where, $table=false)
    {
        $whereSql = $this->formatWhereSql($where);
        
        $table = $table?$table:$this->tableName;

        $sql = 'SELECT count(*) as total FROM '. $this->_prefix['primary'] . $table .' where '. $whereSql;

        return intval($this->db->getone($sql));
    }

    /*
    * 20180927
    * 新增模型查询方法
    * $where  为字符串
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回一维数组
    */
    public function findBySql($where, $select="*", $table=false)
    {
        if (is_array($select)) $select = implode(',', $select);

        $table = $table?$table:$this->tableName;

        $sql = 'SELECT '. $select .' FROM '. $this->_prefix['primary'] . $table .' where '. $where .' limit 1';

        return $this->db->getrow($sql);
    }
    
    /*
     * 20180927
     * 新增模型查询方法
     * $where  为字符串
     * $select 可为数组或字符串
     * $select 为数组时，是字段数组
     * 返回int
     */
    public function findOneBySql($where, $select="id", $table=false)
    {
        if (is_array($select)) $select = implode(',', $select);
    
        $table = $table?$table:$this->tableName;
    
        $sql = 'SELECT '. $select .' FROM '. $this->_prefix['primary'] . $table .' where '. $where .' limit 1';
    
        return $this->db->getone($sql);
    }


    /*
    * 20180927
    * 新增模型查询方法 统计
    * $where  为字符串
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回int
    */
    public function countBySql($where, $table=false)
    {
        $table = $table?$table:$this->tableName;

        $sql = 'SELECT count(*) as total FROM '. $this->_prefix['primary'] . $table .' where '. $where;

        return intval($this->db->getone($sql));
    }


        /*
    * 20180927
    * 新增模型查询方法
    * $where  为字符串
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回二维数组
    */
    public function findAllBySql($where, $select="*", $table=false)
    {

        if (is_array($select)) $select = implode(',', $select);

        $table = $table?$table:$this->tableName;

        $sql = 'SELECT '. $select .' FROM '. $this->_prefix['primary'] . $table .' where '. $where;

        return $this->db->sql($sql);
    }

    /*
    * 20180927
    * 新增模型查询方法获取某一列数据
    * $where  为字符串
    * $select 可为数组或字符串
    * $select 为数组时，是字段数组
    * 返回一维数组
    */
    public function findColumnBySql($where, $column, $table=false)
    {
        
        $table = $table?$table:$this->tableName;

        $sql = 'SELECT `'. $column .'` FROM '. $this->_prefix['primary'] . $table .' where '. $where;

        $rows = $this->db->sql($sql);

        if (count($rows)>0) {
            foreach ($rows as $key => $value) {
                $rows[$key] = $value[$column];
            }
        }

        return $rows;
    }


    /*
    * 20180927
    * 新增模型插入方法 
    * $rows 为数组
    * $table 表
    * 返回int
    */
    public function insert($rows, $table=false)
    {
        $table = $table?$table:$this->tableName;

        $keys = [];
        $values = [];

        foreach ($rows as $key => $value) {
            $keys[] = '`'.$key.'`';
            $values[] = " '".$value."' ";
        }

        $sql = 'INSERT INTO '.$this->_prefix['primary'].$table.' ('.implode(',', $keys).') VALUES ('.implode(',', $values).')';
        
        return $this->sql($sql);
    }

    /*
    * 20180927
    * 新增模型批量插入方法 
    * $rows 为数组
    * $table 表
    * 返回int
    */
    public function batchInsert($fields, $rows, $table=false)
    {
        $table = $table?$table:$this->tableName;

        $insert = [];

        foreach ($rows as $row) {
            foreach ($row as $k => $v) {
                $row[$k] = '"'.$v.'"';
            }
            $insert[] = ' ('.implode(',', $row).') ';
        }

        $chunk = array_chunk($insert, 100);

        $this->db->begin();

        $bool = true;

        foreach ($chunk as $key => $value) {
            $sql = 'INSERT INTO '.$this->_prefix['primary'].$table.' ('.implode(',', $fields).') VALUES ' . implode(',', $value);
            $res = $this->sql($sql);
            if ($res <=0) {
                $bool = false;
                break;
            }
        }

        if($bool) {
            $this->db->commit();
            return count($rows);
        } else {
            $this->db->rollback();
            return 0;
        }
    }

    /*
    * 20180927
    * 新增模型批量插入方法 
    * $rows 为数组
    * $table 表
    * 返回int
    */
    public function insertBatch($rows, $table=false)
    {
        $table = $table?$table:$this->tableName;

        $insert = [];

        foreach ($rows as $row) {
            foreach ($row as $k => $v) {
                $row[$k] = '"'.$v.'"';
            }
            $insert[] = ' ('.implode(',', $row).') ';
        }

        $fields = array_keys($rows[0]);

        $chunk = array_chunk($insert, 100);

        foreach ($chunk as $key => $value) {
            $sql = 'INSERT INTO '.$this->_prefix['primary'].$table.' ('.implode(',', $fields).') VALUES ' . implode(',', $value);
            $res = $this->sql($sql);
            if ($res <=0) {
                return false;
            }
        }

        return true;
    }

    /*
    * 20180927
    * 新增模型更新方法 
    * $rows 为数组
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $table 表
    * 返回int
    */
    public function update($rows, $where ,$table=false)
    {
        $table = $table?$table:$this->tableName;
        $update = [];
        foreach ($rows as $key => $value) {
            $update[] = '`'.$key."` ='".$value."'";
        }

        $whereSql = $this->formatWhereSql($where);

        $sql = 'UPDATE '.$this->_prefix['primary'].$table.' set '.implode(',', $update). ' where '.$whereSql;
        return $this->sql($sql);
    }

    /*
    * 20180927
    * 新增模型更新方法 SQL
    * $rows 为数组
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $table 表
    * 返回int
    */
    public function updateBySql($sql, $whereSql ,$table=false)
    {
        $table = $table?$table:$this->tableName;

        $sql = 'UPDATE '.$this->_prefix['primary'].$table.' set '.$sql. ' where '.$whereSql;

        return $this->sql($sql);
    }

    /*
    * 20180927
    * 新增模型删除方法 
    * $rows 为数组
    * $where  可为数组或字符串
    * $where  为数组时,必须三个参数，第一个是字段，第二个是判断，第三个是值
    * $table 表
    * 返回int
    */
    public function delete($where, $table=false)
    {
        $table = $table?$table:$this->tableName;
    
        $whereSql = $this->formatWhereSql($where);

        $sql = 'DELETE FROM '.$this->_prefix['primary'].$table.' where '.$whereSql;

        return $this->sql($sql);
    }


    /*
    * 20180927
    * 格式化为where语句
    */
    protected function formatWhereSql($where)
    {
        if (is_array($where)) {
            $whereArray = [];
            foreach ($where as $key => $value) {
                if (strtolower(trim($value[1])) == "in") {
                    $val = $value[2];
                    if (is_array($value[2])){
                        $arr = array();
                        foreach ($value[2] as $k => $v) {
                            $arr[] = "'".$v."'";
                        }
                        $val = implode(',', $arr);
                    }
                    $val = " (".$val.") ";
                }else{
                    $val = " '".$value[2]."' ";
                }

                $whereArray[] = ' `'.$value[0].'` ' . $value[1] .' '. $val;
            }

            $where = implode(' and ', $whereArray);
        }

        return $where;
    }

    //获取的文件
    protected $docids = [];

    //合并docid
    public function addDocId($docid)
    {
        if(is_array($docid)){
            $this->docids = array_merge( $this->docids, $docid);
        }else{
            $this->docids[] = intval($docid);
        }
    }

    //获取添加后的所有文件
    public function getDocuments()
    {
        if($this->docids){
            return $this->getDocs($this->docids);
        }
        return [];
    }

    //通过docid获取文件
    public function getDocs($docid)
    {
        if (is_array($docid)) {
            $docid = array_filter($docid,function($v){
                return $v&&$v>0;
            });
            
            if(count($docid) == 0 ) {
                return [];
            }

            $where = " WHERE `stat`=1 AND `docid` IN (" . implode(",", array_unique($docid)) . ")";
        } else {
            $where = " WHERE `stat`=1 AND `docid`=" . intval($docid);
        }

        $sql = "SELECT `docid`,`filename`,`create_time` FROM {$this->_prefix['primary']}documents " . $where;
        $rs = $this->sql($sql);
        if ($rs) {
            foreach ($rs as $r) {
                $doc[$r['docid']] = $this->c['doc_host'] . date("Ymd", $r['create_time']) . "/" . date("H", $r['create_time']) . "/" . date("i", $r['create_time']) . "/" . $r['filename'];
            }
            return $doc;
        } else {
            return [];
        }

    }

    //获取文件地址
    public function getDocFileUrl($filename,$create_time)
    {
        return $this->c['doc_host'] . date("Ymd", $create_time) . "/" . date("H", $create_time) . "/" . date("i", $create_time) . "/" . $filename;
    }
    /*
    * 获取指定键请求数据
    * 返回int
    */
    protected function request_int($key, $data=false)
    {
        $data = $data ? $data : $_REQUEST;
        if(isset($data[$key])){
            return intval($data[$key]);
        }
        return 0;
    }
    /*
    * 获取指定键请求数据
    * 返回string
    */
    protected function request_str($key, $data=false)
    {
        $data = $data ? $data : $_REQUEST;
        if(isset($data[$key])){
            return addslashes(htmlspecialchars(trim($data[$key])));
        }
        return null;
    }

        //上传文件
    public function saveUploadFile($file,$type='upload')
    {
        $c = $this->c[$type];

        if($file['tmp_name'] == "" || $file['size'] <= 0) return ['code'=>900];

        if ($file['size'] >= $c['size']) return ['code'=>704];

        $format = $this->upload->rf($file['name']);

        if (!in_array($format, $c['fm'])) return ['code'=>703];

        $time = $_SERVER['REQUEST_TIME'];

        //创建目录
        $dir['date'] = $c['dir'] . date("Ymd", $time);
        if (!file_exists($dir['date'])) {
            mkdir($dir['date']);
        }

        $dir['hour'] = $dir['date'] . DIRECTORY_SEPARATOR . date("H", $time);
        if (!file_exists($dir['hour'])) {
            mkdir($dir['hour']);
        }

        $dir['minute'] = $dir['hour'] . DIRECTORY_SEPARATOR . date("i", $time);
        if (!file_exists($dir['minute'])) {
            mkdir($dir['minute']);
        }

        if (!file_exists($dir['minute'])) return ['code'=>706];

        //重命名
        $filename = md5($file['tmp_name'] .$time) . "." . $format;
        $filepath = $dir['minute'] . DIRECTORY_SEPARATOR . $filename;

        $code = 900;
        $docid = 0;
        $url = '';
        //移动文件
        if (move_uploaded_file($file['tmp_name'], $filepath)) {
            if ($type == "pic") {
                $this->upload->mt($filepath, $filepath, 600, 600);
            }

            $sql   = "INSERT INTO {$this->_prefix['primary']}documents ( `name`, `filename`,`filesize`,`format`,`create_time` ) VALUES ('".$file['name']."','".$filename."','".@filesize($filepath)."','".$format."',".$time.")";
            $docid = $this->sql($sql);

            $code = 200;
            if ($docid <= 0) {
                $code = 701;
                @unlink($filepath);
            }

            $url = $this->c['doc_host'] . date("Ymd", $time) . "/" . date("H", $time) . "/" . date("i", $time) . "/" . $filename;

        } else {
            $code = 705;
        }

        return ['code'=>$code, 'docid'=>$docid, 'url'=>$url];
    }

    // 获取设置
    public function getSetting()
    {
        $sql = "SELECT `setting` FROM {$this->_prefix['primary']}setting LIMIT 1";
        $tmp = $this->db->getone($sql);
        if ($tmp != "") {
            return json_decode($tmp, true);
        }
        
        /* $sql     = "SELECT `setting` FROM {$this->_prefix['primary']}setting ORDER BY `setting_id` DESC LIMIT 1";
        $setting = $this->db->getone($sql);
        if ($setting != "") {
            return json_decode($setting, true);
        } */
    }

    //插入消息
    protected function createUserNotice($uid, $type, $title, $content, $obj_id, $obj_type, $extra = '')
    {
        return $this->table("user_notice")->insert([
            'uid' => $uid,
            'type' => $type,
            'title' => $title,
            'content' => $content,
            'obj_id' => $obj_id,
            'obj_type' => $obj_type,
            'extra' => $extra?json_encode($extra, JSON_UNESCAPED_UNICODE):'',
            'create_time' => time()
        ]);
    }
    //错误
    protected function error($code, $msg='')
    {
        if($this->c['lang'] && file_exists(APP_PATH.'/lang/'.$this->c['lang'].'.php')){
            $lang = include APP_PATH.'/lang/'.$this->c['lang'].'.php';
            if($lang) {
                $msg = $msg ?: (isset($lang[$code])?$lang[$code]:'error');
            }
        }

        return ["code"=>$code,"msg"=>$msg];
    }
    //失败
    protected function fail()
    {
        return $this->error(40100);
    }
    //未找到
    protected function notFound()
    {
        return $this->error(40102);
    }
    //成功
    protected function success($data=[])
    {
        return ["code"=>200, "msg"=>"ok", "body"=>$data];
    }

    //写入用户登录凭证
    public function redisUpdateUserLoginToken($uid, $token)
    {
        return $this->redis->set($this->c['redis']['login_user'].$uid, $token);
    }

    //验证用户登录凭证
    public function checkUserToken($uid, $token)
    {
        //开启则验证
        if($this->c['open_login_redis']) {
            $res = $this->redis->get($this->c['redis']['login_user'].$uid);

            return $token == $res ? true : false;
        }
        return true;
    }


/*-20181030 New Model Query----------------------------*/
}